/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
package org.alfresco.service.cmr.invitation;

import java.util.List;
import java.util.Map;

import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable;

/**
 * The invitation service provides the ability to invite people to resources. For example adding a user to a shared web site. It manages the relationship between person, resource and requestType and may also pass along information such as who is to approve or the expected role of the user.
 * 
 * @author mrogers
 */
public interface InvitationService
{
    /**
     * Get the names of the workflows managed by the invitation service.
     * 
     * @return the names of the workkflows managed by the invitation service.
     */
    @NotAuditable
    public List<String> getInvitationServiceWorkflowNames();

    /**
     * Start the invitation process for a NominatedInvitation for a user who does not yet have an Alfresco User Name The server path is calculated based on the sysAdmin parameters
     * 
     * @param inviteeUserName
     *            Alfresco user name of who should be invited
     * @param ResourceType
     *            resourceType
     * @param resourceName
     * @param inviteeRole
     * @param acceptUrl
     * @param rejectUrl
     * @return the nominated invitation which will contain the invitationId and ticket which will uniqely identify this invitation for the rest of the workflow.
     * @throws InvitationException
     * @throws InvitationExceptionUserError
     * @throws InvitationExceptionForbidden
     */
    @Auditable(parameters = {"inviteeUserName", "resourceType", "resourceName", "inviteeRole", "acceptUrl", "rejectUrl"})
    public NominatedInvitation inviteNominated(String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String acceptUrl,
            String rejectUrl);

    /**
     * Start the invitation process for a NominatedInvitation for a user who does not yet have an Alfresco User NameA new user name will be generated as part of the invitation process. The server path is calculated based on the sysAdmin parameters
     * 
     * @param inviteeFirstName
     * @param inviteeLastName
     * @param inviteeEmail
     * @param Invitation.ResourceType
     *            resourceType
     * @param resourceName
     * @param inviteeRole
     * @param acceptUrl
     * @param rejectUrl
     * @return the nominated invitation which will contain the invitationId and ticket which will uniquely identify this invitation.
     * @throws InvitationException
     * @throws InvitationExceptionUserError
     * @throws InvitationExceptionForbidden
     */
    @Auditable(parameters = {"inviteeFirstName", "inviteeLastName", "inviteeEmail", "resourceType", "resourceName", "inviteeRole", "acceptUrl", "rejectUrl"})
    public NominatedInvitation inviteNominated(String inviteeFirstName, String inviteeLastName, String inviteeEmail, Invitation.ResourceType resourceType, String resourceName,
            String inviteeRole, String acceptUrl, String rejectUrl);

    /**
     * Start the invitation process for a NominatedInvitation for a user who does not yet have an Alfresco User Name
     * 
     * @param inviteeUserName
     *            Alfresco user name of who should be invited
     * @param ResourceType
     *            resourceType
     * @param resourceName
     * @param inviteeRole
     * @param serverPath
     * @param acceptUrl
     * @param rejectUrl
     * @return the nominated invitation which will contain the invitationId and ticket which will uniqely identify this invitation for the rest of the workflow.
     * @throws InvitationException
     * @throws InvitationExceptionUserError
     * @throws InvitationExceptionForbidden
     */
    @Auditable(parameters = {"inviteeUserName", "resourceType", "resourceName", "inviteeRole", "serverPath", "acceptUrl", "rejectUrl"})
    public NominatedInvitation inviteNominated(String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String serverPath,
            String acceptUrl, String rejectUrl);

    /**
     * Start the invitation process for a NominatedInvitation for a user who does not yet have an Alfresco User NameA new user name will be generated as part of the invitation process.
     * 
     * @param inviteeFirstName
     * @param inviteeLastName
     * @param inviteeEmail
     *            String
     * @param resourceType
     *            Invitation.ResourceType
     * @param resourceName
     *            String
     * @param inviteeRole
     * @param serverPath
     * @param acceptUrl
     * @param rejectUrl
     *            String
     * @return the nominated invitation which will contain the invitationId and ticket which will uniquely identify this invitation.
     * @throws InvitationException
     * @throws InvitationExceptionUserError
     * @throws InvitationExceptionForbidden
     */
    @Auditable(parameters = {"inviteeFirstName", "inviteeLastName", "inviteeEmail", "resourceType", "resourceName", "inviteeRole", "serverPath", "acceptUrl", "rejectUrl"})
    public NominatedInvitation inviteNominated(String inviteeFirstName, String inviteeLastName, String inviteeEmail, Invitation.ResourceType resourceType, String resourceName,
            String inviteeRole, String serverPath, String acceptUrl, String rejectUrl);

    /**
     * Start the invitation process for a ModeratedInvitation
     * 
     * @param inviteeUserName
     *            who is to be invited
     * @param Invitation.ResourceType
     *            resourceType what resource type ?
     * @param resourceName
     *            which resource
     * @param inviteeRole
     *            which role ?
     */
    @Auditable(parameters = {"inviteeComments", "inviteeUserName", "resourceType", "resourceName", "inviteeRole"})
    public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole);

    /**
     * Start the invitation process for a ModeratedInvitation
     *
     * @param inviteeUserName
     *            who is to be invited
     * @param Invitation.ResourceType
     *            resourceType what resource type ?
     * @param resourceName
     *            which resource
     * @param inviteeRole
     *            which role ?
     * @param clientName
     *            which client
     */
    @Auditable(parameters = {"inviteeComments", "inviteeUserName", "resourceType", "resourceName", "inviteeRole", "clientName"})
    public ModeratedInvitation inviteModerated(String inviteeComments, String inviteeUserName, Invitation.ResourceType resourceType, String resourceName, String inviteeRole, String clientName);

    /**
     * Update the invitee comments for an existing moderated invitation
     * 
     * @param inviteeId
     * @param siteShortName
     * @param inviteeComments
     * @return the invitation
     */
    @Auditable(parameters = {"inviteeId", "siteShortName", "inviteeComments"})
    ModeratedInvitation updateModeratedInvitation(String inviteeId, String siteShortName, String inviteeComments);

    /**
     * For a Nominated Invitation invitee accepts this invitation
     * 
     * @param request
     * @param ticket
     * @return the invitation
     */
    @Auditable(parameters = {"invitationId", "reason"})
    public Invitation accept(String invitationId, String ticket);

    /**
     * Moderator approves this invitation
     * 
     * @param invitationId
     *            the request to approve
     * @param reason
     *            - comments about the acceptance
     */
    @Auditable(parameters = {"invitationId", "reason"})
    public Invitation approve(String invitationId, String reason);

    /**
     * User or moderator rejects this request
     * 
     * @param invitationId
     * @param reason
     */
    @Auditable(parameters = {"invitationId", "reason"})
    public Invitation reject(String invitationId, String reason);

    /**
     * Moderator approves this invitation
     * 
     * @param siteName
     * @param invitee
     * @param role
     * @param inviter
     */
    @Auditable(parameters = {"siteName", "Invitee", "role", "inviter"})
    public void acceptNominatedInvitation(String siteName, String invitee, String role, String inviter);

    /**
     * Moderator approves this invitation
     * 
     * @param siteName
     * @param invitee
     * @param role
     * @param reviewer
     */
    @Auditable(parameters = {"siteName", "Invitee", "role", "reviewer"})
    public void approveModeratedInvitation(String siteName, String invitee, String role, String reviewer);

    /**
     * Moderator rejects this invitation
     * 
     * @param siteName
     * @param invitee
     * @param role
     * @param reviewer
     * @param resourceType
     * @param reviewComments
     */
    @Auditable(parameters = {"siteName", "Invitee", "role", "reviewer", "resourceType", "reviewComments"})
    public void rejectModeratedInvitation(String siteName, String invitee, String role, String reviewer, String resourceType, String reviewComments);

    /**
     * Inviter cancels this invitation
     * 
     * @param siteName
     * @param invitee
     * @param inviteId
     * @param currentInviteId
     */
    @Auditable(parameters = {"siteName", "Invitee", "inviteId", "currentInviteId"})
    public void cancelInvitation(String siteName, String invitee, String inviteId, String currentInviteId);

    /**
     * cancel this request
     */
    @Auditable(parameters = {"invitationId"})
    public Invitation cancel(String invitationId);

    /**
     * Clean up invitee user account and person node when no longer in use. They are deemed to no longer be in use when the invitee user account is still disabled and there are no outstanding pending invites for that invitee.
     * 
     * @param invitee
     * @param currentInviteId
     */
    @Auditable(parameters = {"Invitee", "currentInviteId"})
    public void deleteAuthenticationIfUnused(String invitee, String currentInviteId);

    /**
     * Implemented for backwards compatibility
     * 
     * @param inviteId
     * @param executionVariables
     * @deprecated
     * @see {@link #sendNominatedInvitation(String, String, String, Map)}
     */
    @Auditable(parameters = {"inviteId"})
    public void sendNominatedInvitation(String inviteId, Map<String, Object> executionVariables);

    /**
     * Sends the invite email using the given template, subject localization key, and variables.
     * 
     * @param inviteId
     * @param emailTemplateXpath
     *            the XPath to the email template in the repository
     * @param emailSubjectKey
     *            the subject of the email
     * @param executionVariables
     *            the variables used to populate the email
     */
    @Auditable(parameters = {"inviteId"})
    public void sendNominatedInvitation(String inviteId, String emailTemplateXpath,
            String emailSubjectKey, Map<String, Object> executionVariables);

    /**
     * get an invitation from its invitation id
     * 
     * @param invitationId;
     */
    @NotAuditable
    public Invitation getInvitation(String invitationId);

    /**
     * list Invitations for a specific person
     */
    @NotAuditable
    public List<Invitation> listPendingInvitationsForInvitee(String invitee);

    @NotAuditable
    public List<Invitation> listPendingInvitationsForInvitee(String invitee, Invitation.ResourceType resourceType);

    /**
     * list Invitations for a specific resource
     * 
     * @param resourceType
     * @param resourceName
     */
    @NotAuditable
    public List<Invitation> listPendingInvitationsForResource(Invitation.ResourceType resourceType, String resourceName);

    /**
     * This is the general search invitation method returning {@link Invitation} This method has a hardcoded limit of 200 invitations to return. It has been deprecated and it is recommended to use the overloaded version for which you can specify an appropriate limit depending on the needs
     * 
     * @param criteria
     *            InvitationSearchCriteria search criteria
     * @return the list of invitations
     * 
     * @deprecated
     */
    @NotAuditable
    public List<Invitation> searchInvitation(InvitationSearchCriteria criteria);

    /**
     * This is the general search invitation method returning {@link Invitation} This is the recommended method to use for searching invitations; Consider that the performance of the method will be greatly influenced by the limit specified
     * 
     * @param criteria
     *            search criteria
     * @param limit
     *            maximum number of IDs to return. If less than 1, there is no limit.
     * @return the list of invitations
     */
    @NotAuditable
    public List<Invitation> searchInvitation(InvitationSearchCriteria criteria, int limit);

    /**
     * @return true if emails are sent on invite.
     */
    @NotAuditable
    boolean isSendEmails();

    /**
     * 
     * Sends the site join request notification email using the given template, subject localization key, and variables.
     * 
     * @param invitationId
     * @param emailTemplateXpath
     * @param emailSubjectKey
     * @param variables
     */
    @Auditable(parameters = {"inviteId"})
    public void sendModeratedInvitation(String invitationId, String emailTemplateXpath, String emailSubjectKey, Map<String, Object> variables);
}
